﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ReadyApps.Wiki;

namespace ReadyAppsTest.Wiki
{
    [TestClass]
    public class EffectivePermissionsTest
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Constructor Tests

        [TestMethod]
        public void EffectivePermissionsConstructorTest()
        {
            EffectivePermissions target = new EffectivePermissions();
            PrivateObject targetWrapper = new PrivateObject(target);
            Assert.AreEqual(WikiPermissions.None, (WikiPermissions)targetWrapper.GetField("permissions"));
        }

        #endregion

        #region Apply Tests

        [TestMethod]
        [Description("Tests the proper merging of effective permissions")]
        public void ApplyTest()
        {
            // Starter, ToApply, Mask, Result
            List<Tuple<WikiPermissions, WikiPermissions, WikiPermissions, WikiPermissions>> testCases =
                new List<Tuple<WikiPermissions, WikiPermissions, WikiPermissions, WikiPermissions>>();
            testCases.Add(new Tuple<WikiPermissions, WikiPermissions, WikiPermissions, WikiPermissions>(
                WikiPermissions.None,
                WikiPermissions.None,
                WikiPermissions.AllPrivileges,
                WikiPermissions.None));
            testCases.Add(new Tuple<WikiPermissions, WikiPermissions, WikiPermissions, WikiPermissions>(
                WikiPermissions.None,
                WikiPermissions.ViewPage,
                WikiPermissions.AllPrivileges,
                WikiPermissions.ViewPage));
            testCases.Add(new Tuple<WikiPermissions, WikiPermissions, WikiPermissions, WikiPermissions>(
                WikiPermissions.None,
                WikiPermissions.ViewPage | WikiPermissions.ManagePublishing,
                WikiPermissions.AllPrivileges,
                WikiPermissions.ViewPage | WikiPermissions.ManagePublishing));
            testCases.Add(new Tuple<WikiPermissions, WikiPermissions, WikiPermissions, WikiPermissions>(
                WikiPermissions.ViewPage,
                WikiPermissions.None,
                WikiPermissions.AllPrivileges,
                WikiPermissions.ViewPage));
            testCases.Add(new Tuple<WikiPermissions, WikiPermissions, WikiPermissions, WikiPermissions>(
                WikiPermissions.None,
                WikiPermissions.ViewPage | WikiPermissions.EditPermissions,
                WikiPermissions.ViewPage,
                WikiPermissions.ViewPage));

            EffectivePermissions target = new EffectivePermissions();
            PrivateObject targetWrapper = new PrivateObject(target);
            EffectivePermissions apply = new EffectivePermissions();
            PrivateObject applyWrapper = new PrivateObject(apply);
            WikiPermissions actual;
            foreach (var testCase in testCases)
            {
                targetWrapper.SetField("permissions", testCase.Item1);
                applyWrapper.SetField("permissions", testCase.Item2);
                target.Apply(apply, testCase.Item3);
                actual = (WikiPermissions)targetWrapper.GetField("permissions");
                Assert.AreEqual(testCase.Item4, actual, string.Format(
                    "Failed on Starter = {0}, ToApply = {1}, Mask = {2}, Expected = {3}, Actual = {4}",
                    testCase.Item1, testCase.Item2, testCase.Item3, testCase.Item4, actual));
            }
        }

        #endregion

        #region Equals Tests

        [TestMethod]
        public void EffectivePermissionsEqualsTest()
        {
            EffectivePermissions target = new EffectivePermissions();
            Assert.IsFalse(target.Equals(null));
            Assert.IsFalse(target.Equals(new object()));

            EffectivePermissions other = new EffectivePermissions();
            Assert.IsTrue(target.Equals(other));

            target.ViewPage = true;
            Assert.IsFalse(target.Equals(other));

            other.ViewPage = true;
            Assert.IsTrue(target.Equals(other));
        }

        #endregion

        #region ToString Tests

        [TestMethod]
        public void ToStringTest()
        {
            List<Tuple<EffectivePermissions, string>> testData = new List<Tuple<EffectivePermissions, string>>();
            testData.Add(new Tuple<EffectivePermissions, string>(new EffectivePermissions(), string.Empty));
            testData.Add(new Tuple<EffectivePermissions, string>(new EffectivePermissions() { ViewPage = true }, "ViewPage"));
            testData.Add(new Tuple<EffectivePermissions, string>(new EffectivePermissions() { EditPage = true }, "EditPage"));
            testData.Add(new Tuple<EffectivePermissions, string>(new EffectivePermissions() { EditPermissions = true }, "EditPermissions"));
            testData.Add(new Tuple<EffectivePermissions, string>(new EffectivePermissions() { ManageRevisions = true }, "ManageRevisions"));
            testData.Add(new Tuple<EffectivePermissions, string>(new EffectivePermissions() { ViewPage = true, EditPage = true }, "ViewPage|EditPage"));
            testData.Add(new Tuple<EffectivePermissions, string>(new EffectivePermissions() { EditPage = true, ManageRevisions = true }, "EditPage|ManageRevisions"));

            foreach (var testCase in testData)
            {
                Assert.AreEqual(testCase.Item1.ToString(), string.Format("EffectivePermissions{{{0}}}", testCase.Item2));
            }
        }

        #endregion

        #region Private Method Tests

        [TestMethod]
        public void GetPermissionTest()
        {
            EffectivePermissions target = new EffectivePermissions();
            PrivateObject targetWrapper = new PrivateObject(target);
            bool expected = false;
            bool actual = (bool)targetWrapper.Invoke("GetPermission", WikiPermissions.ViewPage);
            Assert.AreEqual(expected, actual);

            expected = true;
            target.ViewPage = expected;
            actual = (bool)targetWrapper.Invoke("GetPermission", WikiPermissions.ViewPage);
            Assert.AreEqual(expected, actual);

            target.EditPermissions = false;
            actual = (bool)targetWrapper.Invoke("GetPermission", WikiPermissions.ViewPage);
            Assert.AreEqual(expected, actual);

            target.EditPermissions = true;
            actual = (bool)targetWrapper.Invoke("GetPermission", WikiPermissions.ViewPage);
            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void SetPermissionTest()
        {
            EffectivePermissions target = new EffectivePermissions();
            PrivateObject targetWrapper = new PrivateObject(target);
            bool expected = false;
            Assert.AreEqual(expected, target.ViewPage);

            expected = true;
            targetWrapper.Invoke("SetPermission", WikiPermissions.ViewPage, true);
            Assert.AreEqual(expected, target.ViewPage);
        }

        [TestMethod]
        public void SetPermissionNegativelyTest()
        {
            EffectivePermissions target = new EffectivePermissions();
            PrivateObject targetWrapper = new PrivateObject(target);
            bool expected = false;
            
            targetWrapper.Invoke("SetPermission", WikiPermissions.ViewPage, true);
            targetWrapper.Invoke("SetPermission", WikiPermissions.EditPermissions, false);
            Assert.AreEqual(expected, target.EditPermissions);
            Assert.AreEqual(WikiPermissions.ViewPage, (WikiPermissions)targetWrapper.GetField("permissions"));
        }

        #endregion

        #region Property Tests

        [TestMethod]
        public void ViewPageTest()
        {
            EffectivePermissions target = new EffectivePermissions();
            Assert.AreEqual(false, target.ViewPage);
            bool expected = true;
            bool actual;
            target.ViewPage = expected;
            actual = target.ViewPage;
            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void EditPermissionsTest()
        {
            EffectivePermissions target = new EffectivePermissions();
            Assert.AreEqual(false, target.EditPermissions);
            bool expected = true;
            bool actual;
            target.EditPermissions = expected;
            actual = target.EditPermissions;
            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        [Description("Tests for the proper permissions when security is disabled")]
        public void NonSecurityEnabledPermissionsTest()
        {
            EffectivePermissions target = EffectivePermissions.NonSecurityEnabledPermissions;
            PrivateObject targetWrapper = new PrivateObject(target);
            WikiPermissions actual = (WikiPermissions)targetWrapper.GetField("permissions");
            Assert.AreEqual(WikiPermissions.ViewPage | WikiPermissions.EditPage | WikiPermissions.CreatePage | WikiPermissions.CreateFolder | WikiPermissions.ManageRevisions, actual);
        }

        [TestMethod]
        [Description("Tests for incorrect values when a second property is set")]
        public void ViewPageAndEditPermissionsTest()
        {
            EffectivePermissions target = new EffectivePermissions();
            PrivateObject targetWrapper = new PrivateObject(target);

            target.ViewPage = true;
            target.EditPermissions = false;
            Assert.AreEqual(true, target.ViewPage);
            Assert.AreEqual(false, target.EditPermissions);
            Assert.AreEqual(WikiPermissions.ViewPage, (WikiPermissions)targetWrapper.GetField("permissions"));
        }

        #endregion
    }
}
